package com.cloud.common.exception;

import com.cloud.common.domain.Result;
import com.cloud.exception.CommonException;
import com.cloud.exception.CustomException;
import com.cloud.exception.RollbackException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.sql.SQLException;

/**
 * 全局异常处理器
 *
 * @author yzj
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 自定义业务异常
     */
    @ExceptionHandler(CustomException.class)
    public Result customException(CustomException e) {
        logger.error(e.getMessage(), "内部异常:" + e.getMessage());
        return Result.message(e.getCode(), "内部异常:" + e.getMessage());
    }

    /**
     * 自定义业务异常/SEATA监听事务
     */
    @ExceptionHandler(RollbackException.class)
    public Result rollbackException(RollbackException e, HttpServletResponse response) {
        logger.error(e.getMessage(), "内部异常:" + e.getMessage());
        // 如果开启了分布式事务,设置错的状态码,让事务回滚
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        return Result.message(e.getCode(), "内部异常:" + e.getMessage());
    }

    /**
     * 请求路径异常
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public Result noHandlerFoundException(NoHandlerFoundException e, HttpServletResponse response) {
        logger.error(e.getMessage(), e);
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        return Result.message(CommonException.PATH_NO_EXITS.getCode(), CommonException.PATH_NO_EXITS.getMsg());
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result requestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        logger.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
        return Result.error("请求方式不支持:" + e.getMessage());
    }


    /**
     * 请求参数解析异常
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result messageNotReadableException(HttpMessageNotReadableException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        logger.error("请求地址'{}',参数解析异常'{}'请求", requestURI);
        return Result.error("请求参数解析异常:" + e.getMessage());
    }

    /**
     * 请求地址不存在
     */
    @ExceptionHandler(value = NoSuchMethodException.class)
    public Result noSuchMethodHandler(NoSuchMethodException e) {
        logger.error(e.getMessage());
        return Result.error("请求地址不存在:" + e);
    }

    /**
     * SQL错误异常
     */
    @ExceptionHandler(SQLException.class)
    public Result sqlHandlerException(SQLException e, HttpServletResponse response) {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        logger.error(e.getMessage(), e);
        return Result.message(CommonException.SQL_ERROR.getCode(),
                CommonException.SQL_ERROR.getMsg() + e.getLocalizedMessage());
    }

    /**
     * 实例化异常
     */
    @ExceptionHandler(InstantiationException.class)
    public Result instantiationHandler(InstantiationException e, HttpServletResponse response) {
        logger.error(e.getMessage(), e);
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        return Result.message(CommonException.INSTANTIATE_ERROR.getCode(),
                CommonException.INSTANTIATE_ERROR.getMsg() + e.getLocalizedMessage());
    }

    /**
     * 全局异常拦截
     */
    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e, HttpServletResponse response) {
        logger.error(e.getMessage(), e);
        // 如果开启了分布式事务,设置错的状态码,让事务回滚
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        return Result.error("内部异常" + e.getMessage());
    }

}
